/**.
 * 
 */
package uk.co.lunagroup.xmloperations;

/**
 * 
 * @author Robert Kowalski methods to manipulate cells in 2d String[][] array
 * 
 */

public class ArrayOperations {
	/**
	 * copy range of cells from one array to another
	 * 
	 * @author Robert Kowalski
	 * @param sourceArray
	 *            where from we are copy
	 * @param destArray
	 *            where to copying
	 * @param destY
	 *            to which row in destination array we will copy
	 * @param destX
	 *            to which column in destination array we will copy
	 * @param sourceY
	 *            from which row in source array we will copy
	 * @param sourceX
	 *            from which column in source array we will copy
	 * @param YSize
	 *            how many rows to copy
	 * @param XSize
	 *            how many columns to copy
	 * @return destArray with copied range
	 */
	public static String[][] copyCellRange(final String[][] sourceArray,
			final String[][] destArray, final int destY, final int destX,
			final int sourceY, final int sourceX, final int YSize,
			final int XSize) {

		// first go through rows
		for (int i = 0; i < YSize; i++) {
			// now go through columns
			for (int j = 0; j < XSize; j++) {
				destArray[destX + j][destY + i] = sourceArray[sourceX + j][sourceY
						+ i];
			}
		}

		return destArray;
	}

	/**
	 * . Check number of rows in 2D string array
	 * 
	 * @param arrayToCheck
	 *            array to check
	 * @return nr of columns in array
	 */
	public static int checkArrayXSize(final String[][] arrayToCheck) {

		int arrayXSize = 0;
		arrayXSize = arrayToCheck.length;
		return arrayXSize;

	}

	/**
	 * . Check number of columns in 2D string array
	 * 
	 * @param arrayToCheck
	 *            array to check
	 * @return nr of rows in array
	 */
	public static int checkArrayYSize(final String[][] arrayToCheck) {

		int arrayYSize = 0;
		arrayYSize = arrayToCheck[0].length;
		return arrayYSize;

	}

	/**
	 * . copy cell from one array to the other. arrays and positions of copy as
	 * parameters
	 * 
	 * @param inputRowNumber
	 * @param inputColumnNumber
	 * @param outputRowNumber
	 * @param outputColumnNumber
	 * @param inputArray
	 * @param outputArray
	 * @return output array with copied cells
	 * @replaced by copyCellRange
	 * @deprecated
	 * 
	 */
	@Deprecated
	public static String[][] copyCell(final int inputRowNumber,
			final int inputColumnNumber, final int outputRowNumber,
			final int outputColumnNumber, final String[][] inputArray,
			final String[][] outputArray) {

		// to avoid out of bounds excepiton if row is 0 there is nothing to read
		// debug
		// System.out.println(cell);
		outputArray[outputColumnNumber][outputRowNumber] = inputArray[inputColumnNumber][inputRowNumber];
		return outputArray;
	}

	/**
	 * . this method delete row and returns array shorter by one row. If used in
	 * loop do not forget to change conditions of the loop. Ex. for (int i=0;
	 * i<YSize; i++) { do something .deleteRow(array); i=i-1; YSize=YSize-1; }
	 * 
	 * @param inputArray
	 *            array to be modified
	 * @param row
	 *            row number to delete
	 * @return array without row
	 */
	public static String[][] deleteRow(final String[][] inputArray,
			final int row) {

		int arrayXSize = checkArrayXSize(inputArray);
		int arrayYSize = checkArrayYSize(inputArray);

		// new array which will hold new values. Size as original input table
		// new table will be one row smaller after deleting row
		String[][] outputArray = new String[arrayXSize][arrayYSize - 1];

		// copy rows up to row and then o=mit row and copy rest
		outputArray = copyCellRange(inputArray, outputArray, 0, 0, 0, 0, row,
				arrayXSize);
		outputArray = copyCellRange(inputArray, outputArray, row, 0, row + 1,
				0, arrayYSize - row - 1, arrayXSize);

		// debug
		// printArray(outputArray);
		// end of debug

		return outputArray;

	}

	/**
	 * . method is printing array on standard out
	 * 
	 * @param array
	 *            array to print
	 */

	public static void printArray(final String[][] array) {

		int nrOfRows = checkArrayYSize(array);
		int nrOfColumns = checkArrayXSize(array);

		for (int i = 0; i < nrOfRows; i++) {
			System.out.print("ROW " + i + ": ");
			for (int j = 0; j < nrOfColumns; j++) {
				System.out.print(array[j][i] + " ");
			}
			System.out.println();
		}
	}

	/**
	 * . makes a copy of array. Returns array
	 * 
	 * @param array
	 *            array to duplicate
	 * @return array copy of an array
	 */
	public static String[][] cloneArray(final String[][] array) {
		return array;
	}

	/**
	 * . change size of the array and keeping current content
	 * 
	 * @param array
	 *            array to resize
	 * @param addColumns
	 *            how many columns to add
	 * @param addRows
	 *            how many rows to add
	 * @return resized array
	 */

	public static String[][] resizeArray(final String[][] array,
			final int addColumns, final int addRows) {

		int xSize = checkArrayXSize(array);
		int ySize = checkArrayYSize(array);

		// now create new bigger array
		String[][] newArray = new String[xSize + addColumns][ySize + addRows];

		// and now copy the data from original array to new one
		newArray = copyCellRange(array, newArray, 0, 0, 0, 0, ySize, xSize);

		return newArray;
	}

	/**
	 * . shrinking array by nr of columns/rows preserving data in existing cells
	 * 
	 * @param array
	 *            array to shrink
	 * @param minusColumns
	 *            how many columns to cut
	 * @param minusRows
	 *            how many rows
	 * @return shrinker array
	 */
	public static String[][] shrinkArray(final String[][] array,
			final int minusColumns, final int minusRows) {
		int arrayYSize = checkArrayYSize(array);
		int arrayXSize = checkArrayXSize(array);
		int outputArrayYSize = arrayYSize - minusRows;
		int outputArrayXSize = arrayXSize - minusColumns;

		String[][] outputArray = new String[outputArrayXSize][outputArrayYSize];
		outputArray = copyCellRange(array, outputArray, 0, 0, 0, 0,
				outputArrayYSize, outputArrayXSize);
		return outputArray;
	}

	/**
	 * . copy row from sourceArray to destArray with destY sourceY parameters
	 * 
	 * @param sourceArray
	 *            where from to copy
	 * @param targetArray
	 *            where to copy
	 * @param destY
	 *            which in destination table should be copied t
	 * @param sourceY
	 *            which row in source table should be copied from
	 * @return returns array with copied row
	 */
	public static String[][] copyRow(final String[][] sourceArray,
			final String[][] targetArray, final int destY, final int sourceY) {

		String[][] destArray = targetArray;
		int sourceArrayXSize = checkArrayXSize(sourceArray);
		int destArrayXSize = checkArrayXSize(destArray);

		if (sourceArrayXSize != destArrayXSize) {
			System.out
					.println("Arrays have different column numbers. Can not copy rows between arrays");
			// TODO add handling for if the arrays are not the same size
		}
		destArray = copyCellRange(sourceArray, destArray, destY, 0, sourceY, 0,
				1, sourceArrayXSize);

		return destArray;
	}

	/**
	 * . checking if the cell has a certain value if yes returns true
	 * 
	 * @param cellToTest
	 *            cell to test
	 * @param valueToCheck
	 *            string to check
	 * @return true if cell contains string which we are looking for
	 */
	public static boolean compareCell(final String cellToTest,
			final String valueToCheck) {
		boolean result = false;

		// second parameter - ONCenter is returning some cells which looks like
		// empty, but it is not empty.
		if (valueToCheck.equals(cellToTest)) {
			result = true;
		}

		return result;
	}

	/**
	 * . inserting zero if cell is empty
	 * 
	 * @param inputArray
	 *            array to fill with zero
	 * 
	 * @return returns array with zero instead of null
	 */
	public static String[][] fillWithZero(final String[][] inputArray) {
		String[][] array = inputArray;
		int xSize = ArrayOperations.checkArrayXSize(array);
		int ySize = ArrayOperations.checkArrayYSize(array);

		for (int i = 0; i < ySize; i++) {
			for (int j = 0; j < xSize; j++) {
				if (array[j][i] == null) {
					array[j][i] = "0";
				}
			}
		}
		return array;
	}

	/**
	 * . Fill whole input array with mark. To avoid problems with null
	 * 
	 * @param inputArray
	 *            array to will up
	 * @param mark
	 *            parameter as string to fill with
	 * @return array with cells filled
	 */
	public static String[][] fillWithMark(final String[][] inputArray,
			final String mark) {
		String[][] array = inputArray;
		int xSize = ArrayOperations.checkArrayXSize(array);
		int ySize = ArrayOperations.checkArrayYSize(array);

		for (int i = 0; i < ySize; i++) {
			for (int j = 0; j < xSize; j++) {
				if (array[j][i] == null) {
					array[j][i] = mark;
				}
			}
		}
		return array;
	}

	/**
	 * . replace cell value in String[][] array with replace String string
	 * 
	 * @param replaceString
	 *            string replace current vale in array
	 * @param columnNr
	 *            column at which value should be replaced
	 * @param rowNumber
	 *            row at which value should be replaced
	 * @param array
	 *            inputArray array where rep
	 * @return array with replace string
	 */
	public static String[][] replace(final String replaceString,
			final int columnNr, final int rowNumber, final String[][] inputArray) {
		String[][] array = inputArray;
		array[columnNr][rowNumber] = replaceString;

		return array;
	}

	/**
	 * . checks if text cell at position columnNr, rowNumber in array match
	 * regExp if so text in cell is replace with value replaceString
	 * 
	 * @param regExp
	 *            regular expression to be checked
	 * @param textToCheck
	 *            text which should be checkd
	 * @param replaceString
	 *            replace string
	 * @param columnNr
	 *            column number
	 * @param rowNr
	 *            row number
	 * @param inputArray
	 *            array to work with
	 * @return true if replaced value, false if not
	 */
	public static boolean checkAndChange(final String regExp,
			final String textToCheck, final String replaceString,
			final int columnNr, final int rowNr, final String[][] inputArray) {
		String[][] array = inputArray;
		boolean test = PatternOperations.checkPattern(regExp, textToCheck);
		boolean result = false;
		if (test == true) {
			// synchronized(array) {//to avoid race conditions
			array = ArrayOperations.replace(replaceString, columnNr, rowNr,
					array);
			result = true;
		}
		return result;
	}
}
